package com.train.generator;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.train.batch.enums.impl.JobStatusEnums;
import com.train.order.enums.impl.ConfirmOrderStatusEnums;
import com.train.system.enums.impl.SeatColEnums;
import com.train.system.enums.impl.SeatTypeEnums;
import com.train.system.enums.impl.TrainTypeEnums;
import lombok.SneakyThrows;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * 枚举生成器
 */
public class EnumGenerator {

    private static String path = "web/src/utils/";

    private static String fileNamePath = "enums.js";

    public static void main(String[] args) {
        StringBuilder enumArray = new StringBuilder();
        StringBuilder enumObject = new StringBuilder();
//        genetate(JobStatusEnums.class, enumObject, enumArray);
//        genetate(SeatColEnums.class, enumObject, enumArray);
//        genetate(SeatTypeEnums.class, enumObject, enumArray);
//        genetate(TrainTypeEnums.class, enumObject, enumArray);
        genetate(ConfirmOrderStatusEnums.class, enumObject, enumArray);


        StringBuilder result = enumObject.append("\r\n").append(enumArray);

        //输出到指定路径
        extracted(result);
    }

    @SneakyThrows
    private static void extracted(StringBuilder passengerTypes) {
        //生成path路径
        File file = new File(path, fileNamePath);
        File parentFile = file.getParentFile();
        if (parentFile != null && !parentFile.exists()) {
            parentFile.mkdirs();
        }
        try (OutputStream os = new FileOutputStream(file)) {
            IoUtil.write(os, true, passengerTypes.toString().getBytes(StandardCharsets.UTF_8));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @SneakyThrows
    private static void genetate(Class<?> clazz, StringBuilder builderObject, StringBuilder builderArray) {
        List<Field> fields = new ArrayList<>();
        Field[] declaredFields = clazz.getDeclaredFields();
        for (Field field : declaredFields) {
            if (!Modifier.isPrivate(field.getModifiers()) || "$VALUES".equals(field.getName())) {
                continue;
            }
            fields.add(field);
        }

        String enumConst = StrUtil
                .toUnderlineCase(clazz.getSimpleName()) //转下划线
                .toUpperCase().replace("_ENUMS", ""); //去掉后缀

        Object[] objects = clazz.getEnumConstants();
        Method name = clazz.getMethod("name"); //获取枚举名

        //生成对象
        builderObject.append(enumConst).append(" = {");
        for (int i = 0; i < objects.length; i++) {
            Object obj = objects[i];
            builderObject.append(name.invoke(obj)).append(":");

            //转json
            formatJsonObj(builderObject, fields, clazz, obj);

            if (i < objects.length - 1) {
                builderObject.append(",");
            }
        }
        builderObject.append("};\r\n");

        //生成数组
        builderArray.append(enumConst).append("_ARRAY = [");
        for (int i = 0; i < objects.length; i++) {
            Object obj = objects[i];

            formatJsonObj(builderArray, fields, clazz, obj);

            if (i < objects.length - 1) {
                builderArray.append(",");
            }
        }
        builderArray.append("];\r\n");
    }

    /**
     * 生成枚举json对象{name: value, name: value}
     * @param builderObject
     * @param fields
     * @param clazz
     * @param obj
     */
    @SneakyThrows
    private static void formatJsonObj(StringBuilder builderObject, List<Field> fields, Class<?> clazz, Object obj) {
        builderObject.append("{");
        for (int i = 0; i < fields.size(); i++) {
            Field field = fields.get(i);
            String name = field.getName();
            String getMethod = "get" + name.substring(0, 1).toUpperCase() + name.substring(1);
            builderObject.append(name).append(":\"").append(clazz.getMethod(getMethod).invoke(obj)).append("\"");
            if (i < fields.size() - 1) {
                builderObject.append(",");
            }
        }
        builderObject.append("}");
    }
}
